package blog

import (
	"fmt"
	"strings"
)

func ParseStatusFromString(status string) (*Status, error) {
	for k, v := range StatusValueMap {
		if status == v {
			return &k, nil
		}
	}
	return nil, fmt.Errorf("no support %s", status)
}

// Go 语言如何定义一个枚举(只能在允许的范围类进行选择)
// 文章当前状态
// 枚举定义为 int, 非常节省数据存储空间, int8 1byte  int64 8byte
// bit
// "draft" --> int32(4) * 5 = 20byte
type Status int8

// fmt Stringer
func (s Status) String() string {
	return StatusValueMap[s]
}

// Unmarshaler []byte ----> Object
// 由于需要修改对象 ，必须使用指针
// {"status": "draft"} --> "draft"
func (s *Status) UnmarshalJSON(data []byte) error {
	str := string(data)
	// "draft"  --> draft
	str = strings.Trim(str, `"`)
	for k, v := range StatusValueMap {
		if v == str {
			*s = k
		}
	}
	return nil
}

// Marshaler Object -----> []byte
// Status DRAFT:0, --> draft
// {"status": draft} 这是一个合法json吗
// {"status": "draft"}
func (s Status) MarshalJSON() ([]byte, error) {
	v := StatusValueMap[s]
	v = fmt.Sprintf(`"%s"`, v)
	return []byte(v), nil
}

// Status 如何控制自定义类型的序列化和反序列化
// Json 提供的接口
// Unmarshaler []byte ----> Object
// Unmarshaler is the interface implemented by types
// that can unmarshal a JSON description of themselves.
// The input can be assumed to be a valid encoding of
// a JSON value. UnmarshalJSON must copy the JSON data
// if it wishes to retain the data after returning.
//
// By convention, to approximate the behavior of Unmarshal itself,
// // Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op.
//
//	type Unmarshaler interface {
//		UnmarshalJSON([]byte) error
//	}
//
// Marshaler Object -----> []byte
// Marshaler is the interface implemented by types that
// can marshal themselves into valid JSON.
//
//	type Marshaler interface {
//		MarshalJSON() ([]byte, error)
//	}
//
// 通过常量来进行枚举值的定义
const (
	// 草稿
	DRAFT Status = iota
	// 已发布
	PULISHED

	// // 草稿
	// DRAFT Status = 0
	// // 已发布
	// PULISHED Status = 1
)

var (
	// 映射
	StatusValueMap = map[Status]string{
		DRAFT:    "draft",
		PULISHED: "published",
	}
)

type UpdateMode string

const (
	// Patch   用户只想修改文章的标题:  title, 其他的值都不传
	// 打补丁, 部分更新, 比较大的缺陷: 不能修改为0值 "", 0,
	PATCH = "patch"
	// title = "", 对象的全量更新
	PUT = "put"
)
